﻿#region Copyright information
// 
// Copyright © 2005-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the Biological Object Library and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: DendrogramNode.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@gmail.com
// - Date Created: 2012-12-08 8:26 AM
// - Last Modified: 2013-01-25 3:59 PM
// 
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace BOL.Algorithms.Clustering
{
    public class DendrogramNode<TElement> : IDendrogramNode<TElement>
    {
        #region Public properties

        public int Key { get; set; }

        public IDendrogramNode<TElement> Parent { get; set; }

        public IList<TElement> Elements { get; private set; }

        public IList<IDendrogramNode<TElement>> Children { get; private set; }

        public bool IsRoot { get { return Parent == null; } }

        public bool IsLeaf { get { return Children.Count == 0; } }

        public int Count { get { return Elements.Count; } }

        public int Depth
        {
            get
            {
                var depth = 0;
                IDendrogramNode<TElement> node = this;

                while (node.Parent != null)
                {
                    node = node.Parent;
                    depth++;
                }

                return depth;
            }
        }

        #endregion

        #region Constructors

        public DendrogramNode(int key, IEnumerable<TElement> elements)
        {
            Key = key;
            Elements = elements.ToList();
            Children = new List<IDendrogramNode<TElement>>();
        }

        public DendrogramNode(IGrouping<int, TElement> grouping)
            : this(grouping.Key, grouping) { }

        #endregion

        #region IGrouping<TKey, TElement> implementation

        public IEnumerator<TElement> GetEnumerator()
        {
            return Elements.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        #region Public methods

        public void AddChild(IDendrogramNode<TElement> child)
        {
            Children.Add(child);
            child.Parent = this;
        }

        public void RemoveChild(IDendrogramNode<TElement> child)
        {
            Children.Remove(child);
            child.Parent = null;
        }

        #endregion

        #region Object overriden

        public override string ToString()
        {
            return String.Format("{0} ({1})", Key, Count);
        }

        public void ToString(ref string prefix, int level)
        {
            prefix += String.Format("{0}{1}", String.Concat(Enumerable.Repeat("  ", level)), this);
            level++;
            foreach (var child in Children)
            {
                prefix += "\n";
                child.ToString(ref prefix, level);
            }
        }

        #endregion
    }
}